#include "IIC.h"

static void I2C_WriteByte(uint8_t addr, uint8_t data);  //声明I2C_WriteByte函数

// 初始化 I2C1 和 OLED
void IIC1_OLED_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    I2C_InitTypeDef I2C_InitStructure;

    // 使能GPIOB 和 I2C1时钟
    RCC_APB2PeriphClockCmd(OLED_GPIO_CLK, ENABLE);
    RCC_APB1PeriphClockCmd(IIC1_CLK, ENABLE);

    // 配置 SCL(PB6) 和 SDA(PB7) 为开漏输出
    GPIO_InitStructure.GPIO_Pin = OLED_GPIO_SCL_PIN | OLED_GPIO_SDA_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; // 必须为开漏输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(OLED_GPIO_PORT, &GPIO_InitStructure);

    // I2C1 初始化
    I2C_InitStructure.I2C_ClockSpeed = 400000;                                // 设置时钟速率为400kHz
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;                                // I2C模式设置为标准I2C模式
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;                        // I2C时钟的占空比设置为2
    I2C_InitStructure.I2C_OwnAddress1 = 0x00;                                 // 自身地址，这里设置为0
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;                               // 使能应答
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // I2C从机地址模式设置为7位地址模式
    I2C_Init(I2C1, &I2C_InitStructure);
}

void OLED_WriteCmd(unsigned char I2C_Cmd) // 写命令
{
    I2C_WriteByte(0x00, I2C_Cmd);
}

void OLED_WriteData(unsigned char I2C_Data) // 写数据
{
    I2C_WriteByte(0x40, I2C_Data);
}

/*
 * 作用 通过I2C总线写入一个字节数据到指定设备寄存器
 * 参数1: addr: 设备寄存器地址
 * 参数2: data: 要写入的数据
 */
static void I2C_WriteByte(uint8_t addr, uint8_t data)
{
    // 等待I2C总线不忙
    while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY))
        ;

    // 生成起始信号，开始I2C通信
    I2C_GenerateSTART(I2C1, ENABLE);
    // 等待主模式选择完成
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT))
        ; /*EV5,主模式*/

    // 发送器件地址，写入模式（OLED的地址默认是0x78）
    I2C_Send7bitAddress(I2C1, OLED_ADDRESS, I2C_Direction_Transmitter);
    // 等待主模式发送模式选择完成
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
        ;

    // 发送设备寄存器地址
    I2C_SendData(I2C1, addr);
    // 等待字节传输完成
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
        ;

    // 发送要写入的数据
    I2C_SendData(I2C1, data);
    // 等待字节传输完成
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
        ;

    // 生成停止信号，结束I2C通信
    I2C_GenerateSTOP(I2C1, ENABLE);
}

